<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Redux(一) | 小小错题本</title>
    <meta name="description" content="如果要用一句话来概括Redux，那么可以使用官网的这句话：Redux是针对JavaScript应用的可预测状态容器。此句话虽然简单，但包含了以下几个含义：

可预测性(predictable): 因为Redux用了reducer与纯函数(pure function)的概念，每个新的state都会由旧的state建来一个全新的state。因而所有的状态修改都是”可预测的”。
状态容器(st ...">
    <meta name="generator" content="VuePress 1.3.0">
    
    
    <link rel="preload" href="/wrong_question_static_page/assets/css/0.styles.f30cb765.css" as="style"><link rel="preload" href="/wrong_question_static_page/assets/js/app.9022c753.js" as="script"><link rel="preload" href="/wrong_question_static_page/assets/js/4.8c1e4aa5.js" as="script"><link rel="preload" href="/wrong_question_static_page/assets/js/5.33f70f09.js" as="script"><link rel="preload" href="/wrong_question_static_page/assets/js/15.a258b8bb.js" as="script"><link rel="prefetch" href="/wrong_question_static_page/assets/js/1.ec18c3a1.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/10.697d33d5.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/11.488795fa.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/12.12a9963e.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/13.9d026eb1.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/14.c44f0e4a.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/16.92328039.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/17.c4f16e4e.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/18.4dfa396f.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/19.edba2346.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/20.082608a3.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/21.5ae0ad82.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/22.89457782.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/23.53bf9e28.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/24.ae06dfc6.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/25.1d7d04a4.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/6.af07a62f.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/7.2c342931.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/8.2545b8d2.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/9.0eaa1c27.js"><link rel="prefetch" href="/wrong_question_static_page/assets/js/vuejs-paginate.c4011005.js">
    <link rel="stylesheet" href="/wrong_question_static_page/assets/css/0.styles.f30cb765.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div id="vuepress-theme-blog__global-layout"><section id="header-wrapper"><header id="header"><div class="header-wrapper"><div class="title"><a href="/wrong_question_static_page/" class="nav-link home-link">小小错题本 </a></div> <div class="header-right-wrap"><ul class="nav"><li class="nav-item"><a href="/wrong_question_static_page/tag/" class="nav-link">分类</a></li></ul> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <!----></div></div></header></section> <div id="mobile-header"><div class="mobile-header-bar"><div class="mobile-header-title"><a href="/wrong_question_static_page/" class="nav-link mobile-home-link">小小错题本 </a> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg></div> <div class="mobile-menu-wrapper"><hr class="menu-divider"> <ul class="mobile-nav"><li class="mobile-nav-item"><a href="/wrong_question_static_page/tag/" class="nav-link">分类</a></li> <li class="mobile-nav-item"><!----></li></ul></div></div></div> <div class="content-wrapper"><div id="vuepress-theme-blog__post-layout"><article itemscope="itemscope" itemtype="https://schema.org/BlogPosting" class="vuepress-blog-theme-content"><header><h1 itemprop="name headline" class="post-title">
        Redux(一)
      </h1> <div class="post-meta"><!----> <div class="post-meta-date"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clock"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg> <time pubdate itemprop="datePublished" datetime="2018-08-22T22:00:38.000Z">
      Thu Aug 23 2018
    </time></div> <ul itemprop="keywords" class="post-meta-tags"><li class="post-tag" data-v-2ac33c20><a href="/wrong_question_static_page/tag/react" data-v-2ac33c20> react </a></li><li class="post-tag" data-v-2ac33c20><a href="/wrong_question_static_page/tag/redux" data-v-2ac33c20> redux </a></li><li class="post-tag" data-v-2ac33c20><a href="/wrong_question_static_page/tag/前端" data-v-2ac33c20> 前端 </a></li></ul></div></header> <div itemprop="articleBody" class="content__default"><blockquote><p>如果要用一句话来概括Redux，那么可以使用官网的这句话：Redux是针对JavaScript应用的可预测状态容器。此句话虽然简单，但包含了以下几个含义：</p></blockquote> <ul><li>可预测性(predictable): 因为Redux用了reducer与纯函数(pure function)的概念，每个新的state都会由旧的state建来一个全新的state。因而所有的状态修改都是”可预测的”。</li> <li>状态容器(state container): state是集中在单一个对象树状结构下的单一store，store即是应用程序领域(app domain)的状态集合。</li> <li>JavaScript应用: 这说明Redux并不是单指设计给React用的，它是独立的一个函数库，可通用于各种JavaScript应用。</li></ul> <blockquote><p>Redux基于简化版本的Flux框架，Flux是Facebook开发的一个框架。在标准的MVC框架中，数据可以在UI组件和存储之间双向流动，而Redux严格限制了 <em><strong>数据只能在一个方向上流动</strong></em>。</p></blockquote> <p><a href="https://imgchr.com/i/PTGuW9" target="_blank" rel="noopener noreferrer"><img src="https://s1.ax1x.com/2018/08/22/PTGuW9.md.png" alt="PTGuW9.md.png"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <p>为了说明整个模型的运作流程，首先我们需要弄清Redux模型中的几个组成对象：action 、reducer、store。</p> <ul><li>action：官方的解释是action是把数据从应用传到 store 的有效载荷，它是 store 数据的唯一来源；要通过本地或远程组件更改状态，需要分发一个action；</li> <li>reducer：action发出了做某件事的请求，只是描述了要做某件事，并没有去改变state来更新界面，reducer就是根据action的type来处理不同的事件；</li> <li>store：store就是把action和reducer联系到一起的对象，store本质上是一个状态树，保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。</li></ul> <p>在Redux中，所有的数据（比如state）被保存在一个被称为store的容器中 ，在一个应用程序中只能有一个store对象。当一个store接收到一个action，它将把这个action代理给相关的reducer。reducer是一个纯函数，它可以查看之前的状态，执行一个action并且返回一个新的状态。</p> <h2 id="redux配置"><a href="#redux配置" class="header-anchor">#</a> Redux配置</h2> <p>配置Redux开发环境的最快方法是使用create-react-app工具。在开始之前，确保已经安装并更新了nodejs、npm和yarn。下面以生成一个redux-shopping项目并安装Redux为例。</p> <p>如果没有安装create-react-app工具，请使用下面的命令先执行安装操作。</p> <div class="language-cmd extra-class"><pre class="language-text"><code>npm install -g create-react-app
</code></pre></div><p>然后，在使用下面的命令创建redux-shopping项目。</p> <div class="language-cmd extra-class"><pre class="language-text"><code>create-react-app redux-shopping
cd redux-shopping
yarn add redux
</code></pre></div><p>首先，删除src文件夹中除index.js以外的所有文件。打开index.js，删除所有代码，键入以下内容：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;redux&quot;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">reducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>reducer<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>上面代码的意思是：</p> <ol><li>从redux包中引入createStore()方法；</li> <li>创建了一个名为reducer的方法，第一个参数state是当前保存在store中的数据，第二个参数action是一个容器，用于：
<ul><li>type - 一个简单的字符串常量，例如ADD, UPDATE, DELETE等。</li> <li>payload - 用于更新状态的数据。</li></ul></li> <li>创建一个Redux存储区，它只能使用reducer作为参数来构造。存储在Redux存储区中的数据可以被直接访问，但只能通过提供的reducer进行更新。</li></ol> <p>目前，state为undefined或null，要解决这个问题，需要分配一个默认的值给state，使其成为一个空数组。例如：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">reducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>目前我们创建的reducer是通用的，那么我们如何使用多个reducer呢？此时我们可以使用Redux包中提供的combineReducers函数。做如下内容修改：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/index.js</span>

<span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;redux&quot;</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> combineReducers <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">productsReducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token function-variable function">cartReducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> allReducers <span class="token operator">=</span> <span class="token punctuation">{</span>
  products<span class="token operator">:</span> productsReducer<span class="token punctuation">,</span>
  shoppingCart<span class="token operator">:</span> cartReducer
<span class="token punctuation">}</span>

<span class="token keyword">const</span> rootReducer <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span>allReducers<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>rootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>接下来，我们将为reducer定义一些测试数据。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/index.js</span>

…

<span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span>
  cart<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      product<span class="token operator">:</span> <span class="token string">'bread 700g'</span><span class="token punctuation">,</span>
      quantity<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span>
      unitCost<span class="token operator">:</span> <span class="token number">90</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      product<span class="token operator">:</span> <span class="token string">'milk 500ml'</span><span class="token punctuation">,</span>
      quantity<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
      unitCost<span class="token operator">:</span> <span class="token number">47</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token function-variable function">cartReducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span>initialState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

…

<span class="token keyword">let</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>rootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;initial state: &quot;</span><span class="token punctuation">,</span> store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>接下来，我们可以在终端中执行npm start或者yarn start来运行dev服务器，并在控制台中查看state。</p> <p><img src="https://s1.ax1x.com/2018/08/22/PTtSiD.jpg" alt="PTtSiD.jpg"></p> <p>现在，我们的cartReducer什么也没做，但它应该在Redux的存储区中管理购物车商品的状态。我们需要定义添加、更新和删除商品的操作(action)。此时我们可以做如下的一些定义：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/index.js</span>

…

<span class="token keyword">const</span> <span class="token constant">ADD_TO_CART</span> <span class="token operator">=</span> <span class="token string">'ADD_TO_CART'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">cartReducer</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span>initialState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token constant">ADD_TO_CART</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span>state<span class="token punctuation">,</span>
        cart<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>state<span class="token punctuation">.</span>cart<span class="token punctuation">,</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">default</span><span class="token operator">:</span>
      <span class="token keyword">return</span> state<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

…
</code></pre></div><p>我们继续来分析一下代码。一个reducer需要处理不同的action类型，因此我们需要一个SWITCH语句。当一个ADD_TO_CART类型的action在应用程序中分发时，switch中的代码将处理它。</p> <p>接下来，我们将定义一个action，作为store.dispatch()的一个参数。action是一个Javascript对象，有一个必须的type和可选的payload。我们在cartReducer函数后定义一个：</p> <div class="language-js extra-class"><pre class="language-js"><code>…
<span class="token keyword">function</span> <span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token parameter">product<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> unitCost</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    type<span class="token operator">:</span> <span class="token constant">ADD_TO_CART</span><span class="token punctuation">,</span>
    payload<span class="token operator">:</span> <span class="token punctuation">{</span> product<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> unitCost <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
…
</code></pre></div><p>在这里，我们定义了一个函数，返回一个JavaScript对象。在我们分发消息之前，我们添加一些代码，让我们能够监听store事件的更改。</p> <div class="language-js extra-class"><pre class="language-js"><code>…
<span class="token keyword">let</span> unsubscribe <span class="token operator">=</span> store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">unsubscribe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>接下来，我们通过分发消息到store来向购物车中添加商品。将下面的代码添加在unsubscribe()之前：</p> <div class="language-js extra-class"><pre class="language-js"><code>store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Coffee 500gm'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Flour 1kg'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Juice 2L'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><img src="https://s1.ax1x.com/2018/08/22/PTtBO1.png" alt="PTtBO1.png"></p> <p>到此，我们已经走通了redux的简易流程。不过代码有点乱。维护成本太高。所以我们需要拆分代码。</p> <h2 id="代码拆分"><a href="#代码拆分" class="header-anchor">#</a> 代码拆分</h2> <p>会发现，index.js中的代码逐渐变得冗杂。所以，接下来我们对上面的项目进行一个组织拆分，使之成为Redux项目。首先，在src文件夹中创建一下文件和文件夹，文件结构如下：</p> <div class="language-txt extra-class"><pre class="language-text"><code>src/
├── actions
│ └── cart-actions.js
├── index.js
├── reducers
│ ├── cart-reducer.js
│ ├── index.js
│ └── products-reducer.js
└── store.js
</code></pre></div><p>然后，我们把index.js中的代码进行整理：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/actions/cart-actions.js</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">ADD_TO_CART</span> <span class="token operator">=</span> <span class="token string">'ADD_TO_CART'</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token parameter">product<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> unitCost</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    type<span class="token operator">:</span> <span class="token constant">ADD_TO_CART</span><span class="token punctuation">,</span>
    payload<span class="token operator">:</span> <span class="token punctuation">{</span> product<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> unitCost <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/reducers/cart-reducer.js</span>

<span class="token keyword">import</span>  <span class="token punctuation">{</span> <span class="token constant">ADD_TO_CART</span> <span class="token punctuation">}</span>  <span class="token keyword">from</span> <span class="token string">'../actions/cart-actions'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span>
  cart<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      product<span class="token operator">:</span> <span class="token string">'bread 700g'</span><span class="token punctuation">,</span>
      quantity<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span>
      unitCost<span class="token operator">:</span> <span class="token number">90</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      product<span class="token operator">:</span> <span class="token string">'milk 500ml'</span><span class="token punctuation">,</span>
      quantity<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
      unitCost<span class="token operator">:</span> <span class="token number">47</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span>initialState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token constant">ADD_TO_CART</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span>state<span class="token punctuation">,</span>
        cart<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>state<span class="token punctuation">.</span>cart<span class="token punctuation">,</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">default</span><span class="token operator">:</span>
      <span class="token keyword">return</span> state<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/reducers/index.js</span>

<span class="token keyword">import</span> <span class="token punctuation">{</span> combineReducers <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> productsReducer <span class="token keyword">from</span> <span class="token string">'./products-reducer'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> cartReducer <span class="token keyword">from</span> <span class="token string">'./cart-reducer'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> allReducers <span class="token operator">=</span> <span class="token punctuation">{</span>
  products<span class="token operator">:</span> productsReducer<span class="token punctuation">,</span>
  shoppingCart<span class="token operator">:</span> cartReducer
<span class="token punctuation">}</span>

<span class="token keyword">const</span> rootReducer <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span>allReducers<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> rootReducer<span class="token punctuation">;</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/store.js</span>

<span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;redux&quot;</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> rootReducer <span class="token keyword">from</span> <span class="token string">'./reducers'</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>rootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> store<span class="token punctuation">;</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/index.js</span>

<span class="token keyword">import</span> store <span class="token keyword">from</span> <span class="token string">'./store.js'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> addToCart <span class="token punctuation">}</span>  <span class="token keyword">from</span> <span class="token string">'./actions/cart-actions'</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;initial state: &quot;</span><span class="token punctuation">,</span> store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> unsubscribe <span class="token operator">=</span> store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>

store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Coffee 500gm'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Flour 1kg'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">addToCart</span><span class="token punctuation">(</span><span class="token string">'Juice 2L'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">unsubscribe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>整理完代码之后，程序依然会正常运行.现在我们来添加修改和删除购物车中商品的逻辑。修改cart-actions.js和cart-reducer.js文件：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/reducers/cart-actions.js</span>
…
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">UPDATE_CART</span> <span class="token operator">=</span> <span class="token string">'UPDATE_CART'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">DELETE_FROM_CART</span> <span class="token operator">=</span> <span class="token string">'DELETE_FROM_CART'</span><span class="token punctuation">;</span>
…
<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">updateCart</span><span class="token punctuation">(</span><span class="token parameter">product<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> unitCost</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    type<span class="token operator">:</span> <span class="token constant">UPDATE_CART</span><span class="token punctuation">,</span>
    payload<span class="token operator">:</span> <span class="token punctuation">{</span>
      product<span class="token punctuation">,</span>
      quantity<span class="token punctuation">,</span>
      unitCost
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">deleteFromCart</span><span class="token punctuation">(</span><span class="token parameter">product</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    type<span class="token operator">:</span> <span class="token constant">DELETE_FROM_CART</span><span class="token punctuation">,</span>
    payload<span class="token operator">:</span> <span class="token punctuation">{</span>
      product
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/reducers/cart-reducer.js</span>
…
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token operator">=</span>initialState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token constant">ADD_TO_CART</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span>state<span class="token punctuation">,</span>
        cart<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>state<span class="token punctuation">.</span>cart<span class="token punctuation">,</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">case</span> <span class="token constant">UPDATE_CART</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span>state<span class="token punctuation">,</span>
        cart<span class="token operator">:</span> state<span class="token punctuation">.</span>cart<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> item<span class="token punctuation">.</span>product <span class="token operator">===</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">.</span>product <span class="token operator">?</span> action<span class="token punctuation">.</span>payload <span class="token operator">:</span> item<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">case</span> <span class="token constant">DELETE_FROM_CART</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span>state<span class="token punctuation">,</span>
        cart<span class="token operator">:</span> state<span class="token punctuation">.</span>cart<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> item<span class="token punctuation">.</span>product <span class="token operator">!==</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">.</span>product<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">default</span><span class="token operator">:</span>
      <span class="token keyword">return</span> state<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>最后，我们在index.js中分发这两个action：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// Update Cart</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">updateCart</span><span class="token punctuation">(</span><span class="token string">'Flour 1kg'</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Delete from Cart</span>
store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token function">deleteFromCart</span><span class="token punctuation">(</span><span class="token string">'Coffee 500gm'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="使用redux工具进行调试"><a href="#使用redux工具进行调试" class="header-anchor">#</a> 使用Redux工具进行调试</h2> <p>Redux拥有很多第三方的调试工具，可用于分析代码和修复bug。最受欢迎的是time-travelling tool，即redux-devtools-extension。设置它只需要三个步骤。</p> <p>首先，在Chrome中安装Redux Devtools扩展；
然后，在运行Redux应用程序的终端里使用Ctrl+C停止服务器。并用npm或yarn安装redux-devtools-extension包；</p> <div class="language-cmd extra-class"><pre class="language-text"><code>yarn add redux-devtools-extension
</code></pre></div><p>一旦安装完成，我们对store.js稍作修改都会反映到结果上。例如，我们还可以把src/index.js中日志相关的代码删除掉。返回Chrome，右键单击该工具的图标，打开Redux DevTools面板。</p></div> <footer><!----> <hr> <!----></footer></article> <div class="sticker vuepress-toc"><div class="vuepress-toc-item vuepress-toc-h2 active"><a href="#redux配置" title="Redux配置">Redux配置</a></div><div class="vuepress-toc-item vuepress-toc-h2"><a href="#代码拆分" title="代码拆分">代码拆分</a></div><div class="vuepress-toc-item vuepress-toc-h2"><a href="#使用redux工具进行调试" title="使用Redux工具进行调试">使用Redux工具进行调试</a></div></div></div></div> <footer class="footer" data-v-06e1b74b><div class="footer-left-wrap" data-v-06e1b74b><ul class="contact" data-v-06e1b74b></ul></div> <div class="footer-right-wrap" data-v-06e1b74b><ul class="copyright" data-v-06e1b74b></ul></div></footer></div><div class="global-ui"><!----></div></div>
    <script src="/wrong_question_static_page/assets/js/app.9022c753.js" defer></script><script src="/wrong_question_static_page/assets/js/4.8c1e4aa5.js" defer></script><script src="/wrong_question_static_page/assets/js/5.33f70f09.js" defer></script><script src="/wrong_question_static_page/assets/js/15.a258b8bb.js" defer></script>
  </body>
</html>
